﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;

namespace ZDMHelper
{
    class CADOperations
    {
        private Database database;
        private Editor editor;
        //private Transaction transaction;
        public CADOperations(Database database, Editor editor)
        {
            this.database = database;
            this.editor = editor;
        }

        /// <summary>
        /// 添加实体
        /// </summary>
        /// <param name="ent">实体</param>
        /// <returns>实体ID</returns>
        private ObjectId AppendEntity(Entity entity)
        {
            ObjectId objectId = new ObjectId(); 
            Transaction trans = this.database.TransactionManager.StartTransaction();
            try
            {
                //获得当前空间块表记录
                BlockTable bt = (BlockTable)trans.GetObject(this.database.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(this.database.CurrentSpaceId, OpenMode.ForWrite);
                //添加实体
                objectId = btr.AppendEntity(entity);
                trans.AddNewlyCreatedDBObject(entity, true);
                trans.Commit();
            }
            catch
            {
                editor.WriteMessage("");
            }
            finally
            {
                trans.Dispose();
            }
            return objectId;
        }

        /// <summary>
        /// 创建标高符号
        /// </summary>
        /// <param name="layerID">层ID</param>
        /// <param name="point">基点</param>
        /// <param name="direction">绘制方向</param>
        private void CreateTriSymbol(ObjectId layerID, Point3d point, LineDirection direction)
        {
            Point3d pt1 = point;                                          //三角形第一个点
            Point3d pt2 = new Point3d(point.X - 1.0, point.Y + 1.5, 0);   //三角形第二个点
            Point3d pt3 = new Point3d(point.X + 1.0, point.Y + 1.5, 0);   //三角形第三个点
            Point3d pt4;                                                  //直线第一个点
            Point3d pt5;                                                  //直线第二个点
            if (direction == LineDirection.LeftToRight)
            {
                pt4 = new Point3d(point.X - 1.5, point.Y, 0);
                pt5 = new Point3d(point.X + 16.0, point.Y, 0);
            }
            else
            {
                pt4 = new Point3d(point.X - 16.0, point.Y, 0);
                pt5 = new Point3d(point.X + 1.5, point.Y, 0);
            }
            Line line1 = new Line(pt1, pt2);
            line1.LayerId = layerID;
            AppendEntity(line1);
            Line line2 = new Line(pt1, pt3);
            line2.LayerId = layerID;
            AppendEntity(line2);
            Line line3 = new Line(pt2, pt3);
            line3.LayerId = layerID;
            AppendEntity(line3);
            Line line4 = new Line(pt4, pt5);
            line4.LayerId = layerID;
            AppendEntity(line4);
        }

        /// <summary>
        /// 创建水位标高符号
        /// </summary>
        /// <param name="layerID">层ID</param>
        /// <param name="point">基点</param>
        /// <param name="direction">绘制方向</param>
        private void CreateRiverTriSymbol(ObjectId layerID, Point3d point, LineDirection direction)
        {
            CreateTriSymbol(layerID, point, direction);
            for (int i = 0; i < 3; i++)
            {
                Point3d pt1 = new Point3d(point.X - 1.0 + i * 0.4, point.Y - (i + 1) * 0.5, 0);
                Point3d pt2 = new Point3d(point.X + 1.0 - i * 0.4, point.Y - (i + 1) * 0.5, 0);
                Line line1 = new Line(pt1, pt2);
                line1.LayerId = layerID;
                AppendEntity(line1);
            }
        }

        /// <summary>
        /// 创建单行文字
        /// </summary>
        /// <param name="text">文字内容</param>
        /// <param name="position">文字位置</param>
        /// <param name="height">文字高度</param>
        /// <param name="rotation">文字旋转</param>
        /// <param name="styleID">文字样式</param>
        /// <param name="layerID">图层</param>
        private void CreateDBText(string text, Point3d position, double height, double rotation, ObjectId styleID, ObjectId layerID)
        {
            DBText dbText = new DBText();
            dbText.TextString = text;
            dbText.Position = position;
            dbText.Height = height;
            dbText.Rotation = rotation;
            dbText.TextStyle = styleID;
            dbText.LayerId = layerID;
            dbText.WidthFactor = 0.7;
            AppendEntity(dbText);
        }

        /// <summary>
        /// 创建多行文字
        /// </summary>
        /// <param name="text">文字内容</param>
        /// <param name="position">文字位置</param>
        /// <param name="height">文字高度</param>
        /// <param name="rotation">文字旋转</param>
        /// <param name="styleID">文字样式</param>
        /// <param name="layerID">图层</param>
        private void CreateMText(string text, Point3d position, double height, double rotation, ObjectId styleID, ObjectId layerID)
        {
            MText mText = new MText();
            mText.LayerId = layerID;
            mText.TextStyle = styleID;
            mText.TextHeight = height;
            mText.Rotation = rotation;
            mText.Location = position;
            mText.Width = height;
            mText.ColorIndex = 1;
            mText.Contents = text;
            AppendEntity(mText);
        }

        /// <summary>
        /// 创建层
        /// </summary>
        /// <param name="layerName">层的名字</param>
        /// <param name="colorIndex">层的颜色</param>
        /// <returns>层ID</returns>
        public ObjectId CreareLayer(string layerName, short colorIndex)
        {
            ObjectId layerId;
            Transaction trans = this.database.TransactionManager.StartTransaction();
            //获得层表
            LayerTable lt = (LayerTable)trans.GetObject(this.database.LayerTableId, OpenMode.ForWrite);
            LayerTableRecord ltr;
            //如果存在，修改层颜色及其他参数
            if (lt.Has(layerName))
            {
                layerId = lt[layerName];
                //设置层的颜色为colorIndex
                ltr = (LayerTableRecord)trans.GetObject(layerId, OpenMode.ForWrite);
                ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex);
            }
            else
            {
                //如果layerName层不存在，创建layerName层
                ltr = new LayerTableRecord();
                ltr.Name = layerName; //设置层的名字
                ltr.Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex);//设置层的颜色
                layerId = lt.Add(ltr);
                trans.AddNewlyCreatedDBObject(ltr, true);
            }
            trans.Commit();
            trans.Dispose();
            return layerId;
        }

        /// <summary>
        /// 创建文字样式
        /// </summary>
        /// <param name="styleName">文字样式名</param>
        /// <returns>文字样式ID</returns>
        public ObjectId CreareTextStyle(string styleName)
        {
            ObjectId textStyleId;
            Transaction trans = this.database.TransactionManager.StartTransaction();
            //获得文字样式表
            TextStyleTable st = (TextStyleTable)trans.GetObject(this.database.TextStyleTableId, OpenMode.ForWrite);
            TextStyleTableRecord str;
            //如果存在。设置字体为宋体，宽度比例为0.7
            if (st.Has(styleName))
            {
                textStyleId = st[styleName];
                str = (TextStyleTableRecord)trans.GetObject(textStyleId, OpenMode.ForWrite);
                str.Font = new Autodesk.AutoCAD.GraphicsInterface.FontDescriptor("宋体", false, false, 0x86, 2);
                str.XScale = 1;
            }
            else
            {
                //如果不存在，创建文字样式
                str = new TextStyleTableRecord();
                str.Name = styleName; //
                str.Font = new Autodesk.AutoCAD.GraphicsInterface.FontDescriptor("宋体", false, false, 0x86, 2);
                str.XScale = 1;
                textStyleId = st.Add(str);
                trans.AddNewlyCreatedDBObject(str, true);
            }
            trans.Commit();
            trans.Dispose();
            return textStyleId;
        }

        /// <summary>
        /// 绘制控制标高
        /// </summary>
        /// <param name="layerID">图层</param>
        /// <param name="styleID">文字样式</param>
        /// <param name="position">位置</param>
        /// <param name="direction">绘制方向</param>
        /// <param name="elevation">控制标高</param>
        public void DrawControlElevation(ObjectId layerID, ObjectId styleID, Point3d position, LineDirection direction, double elevation)
        {
            Point3d textPos1 = new Point3d(position.X + 1.5, position.Y + 0.5, 0);
            if (direction == LineDirection.RightToLeft)
            {
                textPos1 = new Point3d(textPos1.X - 16, textPos1.Y, 0);
            }
            Point3d textPos2 = new Point3d(textPos1.X + 1.2, textPos1.Y, 0);
            CreateTriSymbol(layerID, position, direction);
            CreateDBText("H  " + elevation.ToString() + "m", textPos1, 2.5, 0, styleID, layerID);
            CreateDBText("控", textPos2, 1.5, 0, styleID, layerID);
        }

        /// <summary>
        /// 绘制地面标高
        /// </summary>
        /// <param name="layerID">图层</param>
        /// <param name="styleID">文字样式</param>
        /// <param name="position">位置</param>
        /// <param name="direction">绘制方向</param>
        /// <param name="elevation">地面标高</param>
        public void DrawLoadElevation(ObjectId layerID, ObjectId styleID, Point3d position, LineDirection direction, double elevation)
        {
            Point3d textPos1 = new Point3d(position.X + 1.5, position.Y + 0.5, 0);
            if (direction == LineDirection.RightToLeft)
            {
                textPos1 = new Point3d(textPos1.X - 16.5, textPos1.Y, 0);
            }
            CreateTriSymbol(layerID, position, direction);
            CreateDBText("路面  " + elevation.ToString() + "m", textPos1, 2.5, 0, styleID, layerID);
        }

        /// <summary>
        /// 绘制百年水位
        /// </summary>
        /// <param name="layerID">图层</param>
        /// <param name="styleID">文字样式</param>
        /// <param name="position">位置</param>
        /// <param name="direction">绘制方向</param>
        /// <param name="elevation">百年水位</param>
        public void DrawRiverElevation(ObjectId layerID, ObjectId styleID, Point3d position, LineDirection direction, double elevation)
        {
            Point3d textPos1 = new Point3d(position.X + 1.5, position.Y + 0.5, 0);
            if (direction == LineDirection.RightToLeft)
            {
                textPos1 = new Point3d(textPos1.X - 15, textPos1.Y, 0);
            }
            Point3d textPos2 = new Point3d(textPos1.X + 1.2, textPos1.Y, 0);
            CreateRiverTriSymbol(layerID, position, direction);
            CreateDBText("H   " + elevation.ToString() + "m", textPos1, 2.5, 0, styleID, layerID);
            CreateDBText("通航", textPos2, 1.5, 0, styleID, layerID);
        }

        /// <summary>
        /// 绘制行政区划
        /// </summary>
        /// <param name="layerID">图层</param>
        /// <param name="styleID">文字样式</param>
        /// <param name="position">位置</param>
        /// <param name="data">行政区划数据</param>
        public void DrawRegion(ObjectId layerID, ObjectId styleID, Point3d position, RegionData data)
        {
            string tMileage = "+" + Math.Round(data.Mileage % 1000, 0).ToString();
            Point3d textPos1 = new Point3d(position.X + 1.25, position.Y - 7.5, 0);
            Point3d textPos2 = new Point3d(position.X - 4.5, position.Y - 8.5, 0);
            Point3d textPos3 = new Point3d(position.X + 0.5, position.Y - 8.5, 0);
            Point3d linePos1 = new Point3d(position.X, position.Y - 8, 0); ;
            Point3d linePos2 = new Point3d(position.X, position.Y - 60, 0);
            CreateDBText(tMileage, textPos1, 2.5, Math.PI / 2, styleID, layerID);
            CreateMText(data.FrontRegion, textPos2, 3, 0, styleID, layerID);
            CreateMText(data.BackRegion, textPos3, 3, 0, styleID, layerID);
            Line line = new Line(linePos1, linePos2);
            line.LayerId = layerID;
            line.ColorIndex = 2;
            database.LoadLineTypeFile("ACAD_ISO13W100", "acadiso.lin");
            line.Linetype = "ACAD_ISO13W100";
            line.LinetypeScale = 0.2;
            AppendEntity(line);
        }

        public void DrawGridLine(Point3d startPt, Point3d endPt)
        {
            ObjectId layerId;
            Transaction trans = this.database.TransactionManager.StartTransaction();
            //获得层表
            LayerTable lt = (LayerTable)trans.GetObject(this.database.LayerTableId, OpenMode.ForWrite);
            //LayerTableRecord ltr;
            if (lt.Has("网格线"))
            {
                layerId = lt["网格线"];
                Line line = new Line(startPt, endPt);
                line.LayerId = layerId;
                line.ColorIndex = 30;
                database.LoadLineTypeFile("DOT3", "acadiso.lin");
                line.Linetype = "DOT3";
                AppendEntity(line);
            }
            else
            { }
        }
    }
}
